/**
  ******************************************************************************
  * @file    si2c_sht3x2x.c 
  * @author  make
  * @version V1.0.0
  * @date    2020.10.09
  * @brief   src program body
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "si2c_comm.h"
#include "tskcfg.h"
#include "bsp.h"

#define SHT30_ADDR_BASE         (0x44u)
#define	SHT30_ADDR_WRITE	      (SHT30_ADDR_BASE<<1)
#define	SHT30_ADDR_READ		      ((SHT30_ADDR_BASE<<1)+1)

#define Sht30_Delay(x)          vTaskDelay(x)
#define byte_delay(x)           vTaskDelay(x)

__inline static void sht30_sda_to_in(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	GPIO_InitStruct.Pin   = SHT30_SDA_PIN;
	GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull  = GPIO_PULLUP;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

__inline static void sht30_sda_to_out(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	GPIO_InitStruct.Pin   = SHT30_SDA_PIN;
	GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Pull  = GPIO_PULLUP;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

__inline static void sht30_si2c_delay(void)
{
//  uint16_t delay_time=20;
//	    
//	while(delay_time--); /*7 400khz , 8 370khz*/
//	
	Sht30_Delay(2);
}

__inline static void sht30_si2c_start(void)
{
  sht30_sda_h();
	sht30_scl_h();
  sht30_si2c_delay();
  
	sht30_sda_l();      /* sda一个下降沿 */
  sht30_si2c_delay();
	
	sht30_scl_l();
  sht30_si2c_delay();
}

__inline static void sht30_si2c_stop(void)
{
	sht30_sda_l();
	sht30_scl_h();
	sht30_si2c_delay();
	
	sht30_sda_h();      /* sda一个上升沿 */
  sht30_si2c_delay();
}

__inline static uint8_t sht30_si2c_write_byte(uint8_t dat)  /* 18 */
{
	uint8_t i, ack;
	
	sht30_scl_l();                   /* 保证scl处于低 */
	
	for(i=0; i<8; i++)
	{
		if(0x80 & dat)
		{
			sht30_sda_h();
		}
		else
		{
			sht30_sda_l();
		}
		
		dat <<= 1;
		
		sht30_scl_h();                 /* scl拉高 锁存数据 */
    sht30_si2c_delay();
		
		sht30_scl_l();                 /* scl拉低 准备数据 */
    sht30_si2c_delay();
	}

  sht30_sda_to_in();               /*释放data*/
  
  sht30_scl_h();                   /*第9个时钟的上升沿*/
	sht30_si2c_delay();
	
  if(sht30_sda_r() != 0)
	{
		ack = SI2C_NACK;
	}
	else
	{
		ack = SI2C_ACK;
	}
	
  sht30_scl_l();                   /*第9个时钟的下降沿*/
	sht30_sda_to_out();              /*重新控制总线*/
//  sht30_si2c_delay();
	
	byte_delay(5);
	
  return ack;
}

__inline static uint8_t sht30_si2c_read_byte(uint8_t ack)
{
	uint8_t i;
	uint8_t dat;
	
	dat = 0;
	
	sht30_scl_l();             /* 保证scl处于低 */
	
	sht30_sda_to_in();
	
	for(i=0; i<8; i++)
	{
		sht30_scl_h();                  /* scl拉高后,读出数据 */
    sht30_si2c_delay();
		
		dat <<= 1;
		
		if(sht30_sda_r() != 0)
		{
			dat |= 0x01;
		}
		else
		{
			dat &= 0xfe;
		}
		
		sht30_scl_l();                  /* scl拉低,待对方准备数据 */
    sht30_si2c_delay();
	}
	
	sht30_sda_to_out();
	
	if(ack != SI2C_ACK)
	{
		sht30_sda_h();  /* SI2C_NACK */
	}
	else
	{
		sht30_sda_l();  /* SI2C_ACK */
	}
	
  sht30_scl_h();
  sht30_si2c_delay();             /*发送ack*/
	
  sht30_scl_l();
//  sht30_si2c_delay();
	
	byte_delay(5);
	return dat;
}

static uint8_t si2c_send_cmd(uint8_t addr, uint16_t cmd)
{
	sht30_si2c_start();
	
	if(sht30_si2c_write_byte(addr) != SI2C_ACK)
	{
		sht30_si2c_stop();
		return 1;
	}
	
	if(sht30_si2c_write_byte((uint8_t)(cmd>>8)) != SI2C_ACK)
	{
		sht30_si2c_stop();
		return 2;
	}
	
	if(sht30_si2c_write_byte((uint8_t)cmd) != SI2C_ACK)
	{
		sht30_si2c_stop();
		return 3;
	}
	
	sht30_si2c_stop();
	
	return 0;
}

void sI2C_ResetI2C(void)
{
  uint8_t i;
  
  sht30_sda_h();          /*sda拉高*/
  sht30_scl_l();
  
  for(i=0;i<11;i++)  /*触发9个或者更多的时钟*/
  {
    sht30_scl_h();
		sht30_si2c_delay();
    
    sht30_scl_l();
		sht30_si2c_delay();
  }
}

uint8_t Sht30_ResetCmd(void)
{
  if(si2c_send_cmd(SHT30_ADDR_WRITE, 0x30A2u) != 0)
	{
		return 1;
	}
	
	return 0;
}

uint8_t Sht30_GetSingleMeasure(volatile float *temperature, volatile float *humidity)
{
	uint8_t timeout;
	uint8_t tbuf[2];
	uint8_t hbuf[2];
	uint8_t tcrc, hcrc;
	uint16_t temp, humi;
	
	if(si2c_send_cmd(SHT30_ADDR_WRITE, 0x2400u) != 0)
	{
		return 1;
	}
	
	Sht30_Delay(16);
	
	for(timeout=0; timeout<200; timeout++ )
	{
		sht30_si2c_start();
		
		if(sht30_si2c_write_byte(SHT30_ADDR_READ) == SI2C_ACK)
		{
			break;
		}
		
		sht30_si2c_stop();
		Sht30_Delay(5);
	}
	
	if(timeout >= 200)
	{
		return 2;
	}
	
	tbuf[0] = sht30_si2c_read_byte(SI2C_ACK);
	tbuf[1] = sht30_si2c_read_byte(SI2C_ACK);
	tcrc = sht30_si2c_read_byte(SI2C_ACK);

	hbuf[0] = sht30_si2c_read_byte(SI2C_ACK);
	hbuf[1] = sht30_si2c_read_byte(SI2C_ACK);
	hcrc = sht30_si2c_read_byte(SI2C_NACK);
	
	sht30_si2c_stop();
	
	if(tcrc != sensor_crc8(tbuf, 0xffu))
	{
		return 3;
	}
	
	if(hcrc != sensor_crc8(hbuf, 0xffu))
	{
		return 4;
	}
	
	temp = ((((uint16_t)tbuf[0])<<8)&0xff00) + tbuf[1];
	humi = ((((uint16_t)hbuf[0])<<8)&0xff00) + hbuf[1];
	
	if(temperature != NULL)
	{
		*temperature = (((float)temp / 65535.0) * 175.0) - 45.0;
	}
	
	if(humidity != NULL)
	{
		*humidity = ((float)humi / 65535.0) * 100.0;
	}
	
	return 0;
}
